#include "CompetenceClasse.h"

#include <iostream>

using namespace std;


/**
 * Compétence de classe indéfinie (sans non et avec un coût nul), qui
 * sert lors du renvoi par référence, lorsqu'une compétence n'existe
 * pas.
 */
CompetenceClasse CompetenceClasseInconnue;

/**
 * Permet d'acéder à CompetenceClasseInconnue;
 *
 * @return une référence constante sur CompetenceClasseInconnue;
 */
const CompetenceClasse& competenceClasseInconnue()
{
  return CompetenceClasseInconnue;
}

/******************************************************************************
 *
 * Définition de la classe CompetenceClasse
 *
 *****************************************************************************/

/** Constructeur par défaut.
 * Permet de construire une compétence de classe basique, pouvant
 * éventuellement être associée à un score dépendant du niveau.
 *
 * @param comp nom de la compétence (par défaut "").
 * @param prix coût de la compétence (par défaut 0).
 * @param autre type de la compétence (par défaut Basique).
 */
CompetenceClasse::CompetenceClasse( const string& comp,
				    const unsigned& prix,
				    const ScoreAdditionnel& autre )
  : ADDArticleObjet( "CompetenceClasse", comp, prix ),
    AliasNom( "" ), AliasDefini( false ),
    Pourcentage( false ), ValeurBase( 0 ), AutreScore( autre ),
    SousCategorie( 0 ), AdresseBase( 0 ), SousCategorieDefinie( false ),
    ChoixExclusif( false )
{}

/** Constructeur avec un alias.
 * Permet de construire une compétence de classe basique, dont le nom
 * possède un alias. Est typiquement utilisé pour les sphères et les
 * écoles de magie.
 *
 * @param comp nom de la compétence.
 * @param alias alias de la compétence (càd le nom de fichier /
 * dossier).
 * @param prix coût de la compétence (par défaut 0).
 */
CompetenceClasse::CompetenceClasse( const string& comp, const string& alias,
				    const unsigned& prix )
  : ADDArticleObjet( "CompetenceClasse", comp, prix ), AliasNom( alias ),
    AliasDefini( true ), Pourcentage( false ), ValeurBase( 0 ),
    AutreScore( Normal ), SousCategorie( 0 ), AdresseBase( 0 ),
    SousCategorieDefinie( false ), ChoixExclusif( false )
{}

/**
 * Permet de construire une compétence associée à un pourcentage que
 * l'on peut améliorer par la suite. Est utilisé principalement pour
 * les talents de voleur.
 *
 * @param comp nom de la compétence.
 * @param prix coût de la compétence.
 * @param pourcentage booléen activant le pourcentage évolutif (ne
 * sert qu'à faire la distinction entre ce constructeur et le
 * suivant).
 * @param valBase valeur de base du pourcentage.
 */
CompetenceClasse::CompetenceClasse( const string& comp,
				  const unsigned& prix,
				  const bool& pourcentage,
				  const unsigned& valBase )
  : ADDArticleObjet( "CompetenceClasse", comp, prix ),
    AliasNom( "" ), AliasDefini( false ),
    Pourcentage( pourcentage ), ValeurBase( valBase ), AutreScore( Normal ),
    SousCategorie( 0 ), AdresseBase( 0 ), SousCategorieDefinie( false ),
    ChoixExclusif( false )
{}

/**
 * Permet de construire une compétence "à tiroir", càd la sélection de
 * cette compétence déclenche l'apparition d'un popup qui permet de
 * sélectioner d'autres compétences. Ces compétences ne sont pas à
 * proprement parler des compétences liées à la classe, c'est pourquoi
 * elles sont stockées dans un autre conteneur.
 * 
 * @param comp nom de la compétence.
 * @param prix coût de la compétence.
 * @param base offset appliqué à la compétence pour le stockage dans
 * Classe::Comp_classe (un multiple de 100).
 * @param indice numéro de la liste de compétences "dans le tiroir".
 * @param exclu booléen permettant de choisir entre un choix exclusif
 * ou non (le choix est non-exclusif par défaut).
 */
CompetenceClasse::CompetenceClasse( const string& comp,
				    const unsigned& prix,
				    const unsigned& base,
				    const unsigned& indice,
				    const bool& exclu )
  : ADDArticleObjet( "CompetenceClasse", comp, prix ),
    AliasNom( "" ), AliasDefini( false ),
    Pourcentage( false ), ValeurBase( 0 ), AutreScore( Normal ),
    SousCategorie( indice ), AdresseBase( base ), SousCategorieDefinie( true ),
    ChoixExclusif( exclu )
{}

/** Constructeur de copie.
 * Permet de faire une copie profonde d'une instance de CompetenceClasse.
 *
 * @param lsComp élément à copier.
 */
CompetenceClasse::CompetenceClasse(const CompetenceClasse& lsComp)
  : ADDArticleObjet( lsComp ),
    AliasNom( lsComp.aliasNom() ), AliasDefini( lsComp.aliasDefini() ),
    Pourcentage( lsComp.pourcentage() ), ValeurBase( lsComp.valeurBase() ),
    AutreScore( lsComp.autreScore() ), SousCategorie( lsComp.sousCategorie() ),
    AdresseBase( lsComp.adresseBase() ),
    SousCategorieDefinie( lsComp.sousCategorieDefinie() ),
    ChoixExclusif( lsComp.choixExclusif() )
{}

/**
 * Constructeur utilisé pour les classes dérivées.
 *
 * @param[in] typeObjet type de l'objet.
 * @param[in] comp nom de la "compétence".
 * @param[in] prix coût de la "compétence".
 */
CompetenceClasse::CompetenceClasse( const string& comp, const unsigned& prix,
				    const string& typeObjet )
  : ADDArticleObjet( typeObjet, comp, prix ),
    AliasNom( "" ), AliasDefini( false ),
    Pourcentage( false ), ValeurBase( 0 ), AutreScore( Basique ),
    SousCategorie( 0 ), AdresseBase( 0 ), SousCategorieDefinie( false ),
    ChoixExclusif( false )
{}

/**
 * Destructeur, ne fait rien de spécial.
 */
CompetenceClasse::~CompetenceClasse()
{}

/**
 * Permet de faire une affectation propre depuis une autre CompetenceClasse.
 *
 * @param lsComp élément à copier.
 * @return une référence sur l'instance.
 */
CompetenceClasse& CompetenceClasse::operator=( const CompetenceClasse& lsComp )
{
  Nom                  = lsComp.nom();
  AliasNom             = lsComp.aliasNom();
  Prix                 = lsComp.prix();
  Pourcentage          = lsComp.pourcentage();
  ValeurBase           = lsComp.valeurBase();
  AutreScore           = lsComp.autreScore();
  SousCategorie        = lsComp.sousCategorie();
  AdresseBase          = lsComp.adresseBase();
  SousCategorieDefinie = lsComp.sousCategorieDefinie();
  ChoixExclusif        = lsComp.choixExclusif();

  return *this;
}

/**
 * Permet d'accéder à l'éventuel alias.
 *
 * @return une référence constante sur AliasNom si défini, ou sur Nom.
 */
const string& CompetenceClasse::aliasNom() const
{
  if ( aliasDefini() )
    return AliasNom;
  else
    return nom();
}

/**
 * Permet de modifier la valeur de AliasComp une fois l'instance
 * initialisée.
 *
 * @param alias nouvelle valeur de AliasComp.
 */
void CompetenceClasse::setAliasNom( const string& alias )
{
  AliasNom = alias;
  
  AliasDefini = true;
}

/**
 * Permet de savoir si un alias existe pour le nom de la compétence.
 *
 * @return une référence constante sur AliasDefini.
 */
const bool& CompetenceClasse::aliasDefini() const
{
  return AliasDefini;
}

/**
 * Permet d'accéder à Pourcentage.
 *
 * @return une référence constante sur Pourcentage.
 */
const bool& CompetenceClasse::pourcentage() const
{
  return Pourcentage;
}

/**
 * Permet d'accéder à ValeurBase.
 *
 * @return une référence constante sur ValeurBase.
 */
const unsigned& CompetenceClasse::valeurBase() const
{
  return ValeurBase;
}

/**
 * Permet d'accéder à AutreScore.
 *
 * @return une référence constante sur AutreScore.
 */
const ScoreAdditionnel& CompetenceClasse::autreScore() const
{
  return AutreScore;
}

/**
 * Permet d'accéder à SousCategorie.
 *
 * @return une référence constante sur SousCategorie.
 */
const unsigned& CompetenceClasse::sousCategorie() const
{
  return SousCategorie;
}

/**
 * Permet d'accéder à AdresseBase.
 *
 * @return une référence constante sur AdresseBase.
 */
const unsigned& CompetenceClasse::adresseBase() const
{
  return AdresseBase;
}

/**
 * Permet d'accéder à 
 *
 * @return une référence constante sur SousCategorieDefinie.
 */
const bool& CompetenceClasse::sousCategorieDefinie() const
{
  return SousCategorieDefinie;
}

/**
 * Permet d'accéder à ChoixExclusif.
 *
 * @return une référence constante sur ChoixExclusif.
 */
const bool& CompetenceClasse::choixExclusif() const
{
  return ChoixExclusif;
}

/**
 * Permet d'afficher simplement une instance de CompetenceClasse. On affiche
 * le nom, suivi de l'alias (si existant), le coût et les informations
 * relatives à un éventuel score associé.
 *
 * @param os référence sur le flot de sortie dans lequel seront écrits
 * les champs de l'instance.
 * @param lsComp instance de CompetenceClasse que l'on veut écrire.
 *
 * @return une référence sur le flot utilisé.
 */
ostream& operator<<(ostream& os, const CompetenceClasse& lsComp)
{
  os << lsComp.nom();
  if ( lsComp.aliasDefini() )
    os << " (alias " << lsComp.aliasNom() << ")";
  os << ", coût " << lsComp.prix();
  if ( lsComp.pourcentage() )
    os << " (associé à un pourcentage, valeur de base " << lsComp.valeurBase()
       << ")";
  else if ( lsComp.autreScore() == Basique )
    os << " (associé à un score sur 20 dépendant du niveau)";
  else if ( lsComp.autreScore() == Pourcentage )
    os << " (associé à un pourcentage dépendant du niveau)";
  return os;
}


FlotMessage& operator<<( FlotMessage& flot, const CompetenceClasse& lsComp )
{
  flot << lsComp.nom();
  if ( lsComp.aliasDefini() )
    flot << " (alias " << lsComp.aliasNom() << ")";
  flot << ", coût " << lsComp.prix();
  if ( lsComp.pourcentage() )
    flot << " (associé à un pourcentage, valeur de base " << lsComp.valeurBase()
	 << ")";
  else if ( lsComp.autreScore() == Basique )
    flot << " (associé à un score sur 20 dépendant du niveau)";
  else if ( lsComp.autreScore() == Pourcentage )
    flot << " (associé à un pourcentage dépendant du niveau)";
  return flot;
}
